home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 35 / Amiga Format AFCD35 (Issue 119, Jan 1999).iso / -in_the_mag- / reader_requests / fredobbutils / bbsrc / install.s < prev    next >
Text File  |  1998-11-06  |  11KB  |  571 lines

  1. ; Bootblock Installer V1.0
  2. ; Coded by Frédéric BASSALER in April 1997
  3. ;
  4. ; PUBLIC DOMAIN - Do whatever you want with this source! (improve it!)
  5. ;
  6. ; Assemble with Asm-One, Trash'm-One or PhxAss ...
  7. ;
  8. ;    Frédéric BASSALER
  9. ;    La Serre
  10. ;    19500 COLLONGES
  11. ;    FRANCE
  12. ;
  13. ; fbas@club-internet.fr
  14. ;
  15.  
  16.     incdir    asm:/include/
  17.     include    equ.s
  18.  
  19.     rsreset
  20. argstr        rs.l    1
  21. arglen        rs.l    1
  22. dosbase        rs.l    1
  23. stdio        rs.l    1
  24. fname        rs.l    1
  25. buf        rs.l    1
  26. unitnumber    rs.l    1
  27. unit        rs.l    1
  28. showflag    rs.b    1
  29. VARSIZE        rs.w    0
  30.  
  31. BUFSIZE=$400+20        ;buffer size for bootblock data
  32.  
  33. Start:
  34. ;    lea    fakeargs(pc),a0        ;for debugging purposes
  35. ;    moveq    #fakeargslen,d0
  36.  
  37.     lea    VARS(pc),a5
  38.     move.l    a0,argstr(a5)        ;save CLI/Shell args string
  39.     move.l    d0,arglen(a5)        ;save CLI/Shell args string length
  40.  
  41.     lea    dos.name(pc),a1
  42.     moveq    #0,d0        ;all kickstart versions
  43.     move.l    4.w,a6
  44.     jsr    OpenLibrary(a6)
  45.     move.l    d0,dosbase(a5)
  46.     beq.w    doserr
  47.     move.l    d0,a6
  48.  
  49.     move.l    #outname,d1
  50.     move.l    #1005,d2
  51.     jsr    Open(a6)
  52. ;    jsr    OutPut(a6)
  53.     move.l    d0,stdio(a5)
  54.     beq    CloseAll
  55.  
  56.     clr.b    showflag(a5)
  57.  
  58. ; parse CLI args (very simple parser!)
  59.     move.l    argstr(a5),a0
  60.     move.l    arglen(a5),d0
  61.     clr.b    -1(a0,d0.l)    ;replace LF by 0 (null-character) in ArgString
  62.     subq.l    #1,d0
  63.     beq    usage        ;if no args given => show usage
  64.     bsr    skip_spaces
  65.  
  66.     move.b    (a0)+,d1
  67.     cmp.b    #'-',d1        ;options given?
  68.     bne.s    .no_opt
  69.     move.b    (a0)+,d1
  70.     and.b    #~$20,d1    ;convert character to UPPER case
  71.     cmp.b    #'S',d1        ;option S (SHOW) given?
  72.     seq    showflag(a5)    ;set flag to -1 (true) if yes
  73.  
  74.     bsr    skip_spaces
  75.     move.b    (a0)+,d1
  76. .no_opt
  77.     and.b    #~$20,d1    ;convert character to UPPER case
  78.  
  79.     cmp.b    #'D',d1
  80.     bne.w    usage
  81.     move.b    (a0)+,d1
  82.     and.b    #~$20,d1
  83.     cmp.b    #'F',d1
  84.     bne.w    usage
  85.     moveq    #0,d1
  86.     move.b    (a0)+,d1
  87.     sub.b    #$30,d1
  88.     tst.b    d1
  89.     blt.w    usage
  90.     cmp.b    #3,d1
  91.     bgt.w    usage
  92.     move.l    d1,unitnumber(a5)
  93.  
  94.     cmp.b    #':',(a0)+
  95.     bne    usage
  96.  
  97.     bsr    skip_spaces
  98.  
  99.     tst.b    (a0)
  100.     bne.s    .filename_given
  101.     suba.l    a0,a0
  102. .filename_given
  103.     move.l    a0,fname(a5)
  104.  
  105. ; alloc disk unit
  106.     move.l    unitnumber(a5),d0
  107.     bsr    OpenUnit
  108.     move.l    d0,unit(a5)
  109.     beq    CloseAll
  110.  
  111. ; alloc bootblock buffer
  112.     move.l    #BUFSIZE,d0    ;1kb (2 blocks)
  113.     move.l    #$10002,d1    ;chip!clear
  114.     move.l    4.w,a6
  115.     jsr    AllocMem(a6)
  116.     move.l    d0,buf(a5)
  117.     beq.w    CloseAll
  118.  
  119. ; read old bootblock
  120.     move.l    d0,a0
  121.     move.l    unit(a5),a1
  122.     moveq    #0,d0
  123.     moveq    #2,d1
  124.     bsr    ReadSec
  125.     move.l    unit(a5),a1
  126.     bsr    MotorOff
  127.     tst.l    d0
  128.     bne    readerr
  129.  
  130.     tst.b    showflag(a5)    ;show flag set ?
  131.     bne    ShowBB        ;if yes, display bootblock only
  132.  
  133. ; we want to use the same filesystem on the new bootblock so we need
  134. ; to read which filesystem was used in the old bootblock
  135. ; Please note that we don't check for the first 3 bytes of the data
  136. ; to be 'DOS'. If that first 3 bytes aren't 'DOS', the disk will not boot!
  137.  
  138.     move.l    buf(a5),a0
  139.     lea    boot(pc),a1
  140.     move.b    3(a0),3(a1)
  141.  
  142. ; clear buffer
  143.     move.l    buf(a5),a0
  144.     move    #($400/4)-1,d0
  145. .clr    clr.l    (a0)+
  146.     dbf    d0,.clr
  147.  
  148.     bsr.w    Getfile
  149.     beq.s    .nofile
  150.  
  151.     bra.s    CheckSum
  152.  
  153. ; no filename was given => we'll install the disk with the built-in bootblock
  154. .nofile
  155.     lea    boot(pc),a0
  156.     move.l    buf(a5),a1
  157.     moveq    #(end-boot)-1,d0
  158. .copy    move.b    (a0)+,(a1)+    ;copy bb data to buffer
  159.     dbf    d0,.copy
  160.  
  161. ; calculate the new bootblock's checksum
  162. ; if the checksum isn't correct, the disk won't boot!
  163. CheckSum:
  164.     move.l    buf(a5),a0
  165.     clr.l    4(a0)        ;clear old checksum
  166.     move.l    a0,a1
  167.     moveq    #0,d0
  168.     move    #$ff,d1        ;256-1 longwords
  169. .bcl
  170.     add.l    (a0)+,d0
  171.     bcc.b    .Calc
  172.     addq.l    #1,d0
  173. .Calc    dbf    d1,.bcl
  174.     not.l    d0
  175.     move.l    d0,4(a1)    ;put new checksum
  176.  
  177. ; write new bootblock on disk
  178. writebb:
  179.     move.l    buf(a5),a0
  180.     move.l    unit(a5),a1
  181.     moveq    #0,d0
  182.     moveq    #2,d1
  183.     bsr    WriteSec
  184.     move.l    unit(a5),a1
  185.     bsr    MotorOff
  186.     tst.l    d0
  187.     bne    writeerr
  188.  
  189.     lea    installok.txt(pc),a0
  190.     bsr    Print
  191.  
  192. ; show new bootblock (ASCII dump)
  193. ShowBB:
  194.     lea    viewbb.txt(pc),a0
  195.     bsr    Print
  196.     move.l    buf(a5),a0
  197.     move.l    #$400,d0
  198.     bsr    ConvertChars
  199.     move.b    #$a,0(a0,d0.w)    ;linefeed
  200.     clr.b    1(a0,d0.w)    ;null-terminated string
  201.     bsr    Print
  202.  
  203. *** Close & free all
  204. CloseAll:
  205.     move.l    stdio(a5),d1
  206.     beq.s    .a
  207.     move.l    dosbase(a5),d0
  208.     beq.s    .a
  209.     move.l    d0,a6
  210.     jsr    Close(a6)
  211. .a
  212.     move.l    buf(a5),d0
  213.     beq.b    .b
  214.     move.l    d0,a1
  215.     move.l    #BUFSIZE,d0
  216.     move.l    4.w,a6
  217.     jsr    FreeMem(a6)
  218. .b
  219.     move.l    unit(a5),d0
  220.     beq.s    .c
  221.     move.l    d0,a0
  222.     bsr    CloseUnit
  223. .c
  224.     move.l    dosbase(a5),d0
  225.     beq.b    .d
  226.     move.l    d0,a1
  227.     move.l    4.w,a6
  228.     jsr    CloseLibrary(a6)
  229. .d
  230.     moveq    #0,d0
  231.     rts
  232. err
  233.     moveq    #20,d0        ;Error flag in d0
  234.     rts
  235.  
  236. skip_spaces:
  237.     cmp.b    #$20,(a0)+
  238.     beq.s    skip_spaces
  239.     subq.l    #1,a0
  240.     rts
  241.  
  242. * open & read a bootblock file if specified
  243. Getfile:
  244.     move.l    fname(a5),d1
  245.     beq.s    .nofile
  246.     move.l    #1005,d2    ;mode old
  247.     move.l    dosbase(a5),a6
  248.     jsr    Open(a6)
  249.     move.l    d0,d4
  250.     beq.s    .openerr
  251.     move.l    d4,d1
  252.     move.l    buf(a5),d2
  253.     move.l    #$400,d3
  254.     jsr    Read(a6)
  255.     move.l    d4,d1
  256.     jsr    Close(a6)
  257.     moveq    #1,d0        ;return code: file loaded
  258.     rts
  259. .nofile
  260.     moveq    #0,d0        ;return code: no file or file error
  261.     rts
  262.  
  263. .openerr
  264.     lea    openerr.txt(pc),a0
  265.     suba.l    a1,a1
  266.     bsr.s    Print
  267.     bra.s    .nofile
  268.  
  269. doserr
  270.     lea    doserr.txt(pc),a0
  271.     bra.s    pr0
  272. usage
  273.     lea    usage.txt(pc),a0
  274. pr0    suba.l    a1,a1        ;no args for rawprint
  275.     bra.b    pr
  276. deverr
  277.     lea    deverr.txt(pc),a0
  278.     move.l    unitnumber(a5),a1
  279.     bra.b    pr
  280. readerr
  281.     lea    readerr.txt(pc),a0
  282.     move.l    d0,-(sp)
  283.     move.l    sp,a1
  284.     bsr.b    RawPrint
  285.     move.l    (sp)+,d0
  286.     moveq    #29,d1        ;29 = no disk in drive
  287.     cmp.l    d0,d1
  288.     bne    CloseAll
  289.     lea    nodisk.txt(pc),a0
  290.     bra.s    pr
  291.  
  292. writeerr
  293.     lea    writeerr.txt(pc),a0
  294.     move.l    d0,-(sp)
  295.     move.l    sp,a1
  296.     bsr.b    RawPrint
  297.     move.l    (sp)+,d0
  298.     moveq    #28,d1        ;28 = disk is write-protected
  299.     cmp.l    d0,d1
  300.     bne.w    CloseAll
  301.     lea    protected.txt(pc),a0
  302.  
  303. pr    bsr.b    RawPrint
  304.     bra.w    CloseAll
  305.  
  306. * Convert strings with RawDoFmt() and print to screen
  307. * <-- a0: format string
  308. *    a1: addr of data to be converted
  309. *    a3: addr of target string
  310. RawPrint:
  311.     movem.l    d0-a6,-(sp)
  312.     lea    .pchr(pc),a2
  313.     lea    usage.txt(pc),a3
  314.     move.l    a3,-(sp)
  315.     move.l    4.w,a6
  316.     jsr    -522(a6)    ;RawDoFmt()
  317.     move.l    (sp)+,a0
  318.  
  319.     bra.b    Print0
  320.  
  321. .pchr    move.b    d0,(a3)+
  322.     rts
  323.  
  324. * print a null-terminated string
  325. * <-- a0: string addr
  326. Print:
  327.     movem.l    d0-a6,-(sp)
  328. Print0    move.l    a0,d2
  329.     moveq    #-1,d3
  330. .len    addq.l    #1,d3        ;calculate string length
  331.     tst.b    (a0)+        ;result in d3
  332.     bne.b    .len
  333.     move.l    stdio(a5),d1
  334.     move.l    dosbase(a5),a6
  335.     jsr    Write(a6)
  336.     movem.l    (sp)+,d0-a6
  337.     rts
  338.  
  339. * Convert non-displayable ASCII chars (into displayable ones)
  340. * <-- a0: addr of buffer
  341. * <-- d0: buffer size
  342. ConvertChars:
  343. .CHR="·"
  344.     movem.l    a0/d0-d2,-(sp)
  345.     subq    #1,d0
  346. .t    move.b    #.CHR,d1    ;replacement char.
  347.     move.b    (a0)+,d2
  348.     bclr    #7,d2
  349.     cmp.b    #$20,d2        ;char value < $20(=space)?
  350.     bcs.b    .no        ;if yes, replace
  351.     move.b    d2,d1
  352.     btst    #7,-1(a0)
  353.     beq.b    .no
  354.     bset    #7,d1
  355. .no    move.b    d1,-1(a0)
  356.     dbf    d0,.t
  357.     movem.l    (sp)+,a0/d0-d2
  358.     rts
  359.  
  360. *********************** Trackdisk Support Routines ***************************
  361. * (routines used to access disk tracks)
  362.  
  363. *** Open a trackdisk unit
  364. * <-- d0: unit number (0,..,4)
  365. * --> d0: custom 'Unit' structure returned, or 0 if failed
  366. OpenUnit:
  367.     move.l    d0,d7
  368. * allocate our custom 'Unit' structure
  369. * which contains an IORequest an a MsgPort
  370.     moveq    #34+56,d0    ;size=MP_SIZE+IOStdReq_SIZE
  371.     move.l    #$10001,d1
  372.     move.l    4.w,a6
  373.     jsr    AllocMem(a6)
  374.     move.l    d0,d6
  375.     beq.b    .err
  376. * init MsgPort
  377.     move.l    d6,a1
  378.     lea    56(a1),a1    ;MsgPort address in A1
  379.     move.l    a1,-(sp)
  380.     move.l    276(a6),$10(a1)    ;execbase->thistask in mp_SigTask
  381.     jsr    AddPort(a6)    ;trackdisk message port
  382.     tst.l    d0
  383.     beq.b    .free
  384. * open device
  385.     move.l    d6,a1
  386.     move.l    (sp)+,14(a1)    ;msgport
  387.     move.l    d7,d0        ;unit #
  388.     moveq    #1,d1        ;flags: ALLOW_NON_3_5
  389.     lea    trackname(pc),a0
  390.     jsr    OpenDevice(a6)
  391.     tst.l    d0        ;0=no err
  392.     bne.b    .remport
  393.     move.l    d6,d0        ;return address of our struct. (0=fail)
  394.     rts
  395. .remport
  396.     move.l    d6,a1
  397.     lea    56(a1),a1
  398.     jsr    RemPort(a6)
  399. .free
  400.     move.l    d6,a1
  401.     moveq    #34+56,d0
  402.     jsr    FreeMem(a6)
  403. .err    moveq    #0,d0
  404.     rts
  405.  
  406. *** Close a trackdisk unit, previously opened by OpenUnit
  407. * <-- a0: custom Unit struct of the unit to be closed
  408. CloseUnit:
  409.     move.l    a0,d6
  410.     beq.b    .f
  411.     move.l    a0,-(sp)
  412.     move.l    14(a0),a1
  413.     jsr    RemPort(a6)    ;kill msgport
  414.     move.l    (sp)+,a1
  415.     jsr    CloseDevice(a6)
  416.     move.l    d6,a1
  417.     moveq    #34+56,d0
  418.     jmp    FreeMem(a6)    ;free struct 'unit'
  419. .f    rts
  420.  
  421.  
  422. *** Read disk Sectors
  423. * <--    a0: target address for the data to be read
  424. *     a1: unit
  425. *     d0: disk offset
  426. *    d1: number of sectors to read
  427. * -->    d0: 0 if ok, else fail
  428. ReadSec:
  429.     move.l    d2,-(sp)
  430.     move    #2,28(a1)    ;TD_READ
  431.     move.l    a0,40(a1)    ;io_data
  432.     moveq    #9,d2
  433.     lsl.l    d2,d0        ;d0=d0*512
  434.     lsl.l    d2,d1        ;d1=d1*512
  435.     move.l    d1,36(a1)    ;io_length
  436.     move.l    d0,44(a1)    ;io_offset
  437.     clr.l    52(a1)        ;io_seclabel (not used)
  438.     move.l    (sp)+,d2
  439.     bra.b    do_io
  440.  
  441. *** Write disk Sectors
  442. * <--    a0: source address of the data to be written
  443. *     a1: unit
  444. *     d0: disk offset
  445. *    d1: number of sectors to write
  446. * -->    d0: 0 if ok, else fail
  447. WriteSec:
  448.     move.l    d2,-(sp)
  449.     move    #3,28(a1)    ;TD_WRITE
  450.     move.l    a0,40(a1)    ;io_data
  451.     moveq    #9,d2
  452.     lsl.l    d2,d0        ;d0=d0*512
  453.     lsl.l    d2,d1        ;d1=d1*512
  454.     move.l    d1,36(a1)    ;io_length
  455.     move.l    d0,44(a1)    ;io_offset
  456.     clr.l    52(a1)        ;io_seclabel (not used)
  457.     move.l    (sp)+,d2
  458.     bsr.b    do_io
  459. UpdateSec:
  460.     move    #4,28(a1)    ;TD_UPDATE
  461.     bra.b    do_io
  462.  
  463. *** Test if drive empty
  464. * <-- a1: unit
  465. * --> d0: 0 if there's a disk in the drive unit 
  466. TestUnit:
  467.     move    #14,28(a1)    ;TD_CHANGESTATE
  468. td_    clr.l    36(a1)
  469.     bsr.b    do_io
  470.     move.l    32(a1),d0    ;0=no disk
  471.     rts
  472.  
  473. *** Get the protection status
  474. * <-- a1: unit
  475. * --> d0: 0 if NOT write-protected, any other value if write-protected
  476. TestProt:
  477.     move    #15,28(a1)    ;TD_PROTSTATUS
  478.     bra.b    td_
  479.  
  480. *** Get the number of tracks
  481. * <-- a1: unit
  482. * --> d0: number of tracks
  483. GetNumTracks:
  484.     move    #19,28(a1)    ;TD_GETNUMTRACKS
  485.     bra.b    td_
  486.  
  487. *** Turn motor off
  488. * <-- a1: unit
  489. MotorOff:
  490.     move.l    d0,-(sp)
  491.     move    #9,28(a1)    ;TD_MOTOR
  492.     clr.l    36(a1)        ;0 = off ; 1 = on
  493.     bsr.s    do_io
  494.     move.l    (sp)+,d0
  495.     rts
  496. ;send command to trackdisk device
  497. do_io:
  498.     move.l    a1,-(sp)
  499.     move.l    4.w,a6
  500.     jsr    DoIO(a6)
  501.     move.l    (sp)+,a1
  502.     tst.l    d0
  503.     rts
  504.  
  505.  
  506. ******** Variables
  507. VARS:    dcb.b    VARSIZE,0
  508.  
  509. *** texte
  510. ;fakeargs    dc.b    '-s df0:',0
  511. ;fakeargslen=*-fakeargs
  512.  
  513. outname        dc.b    '*',0
  514. trackname    dc.b    'trackdisk.device',0
  515.  
  516.     even
  517. ver    dc.b    "$VER: BootInstall 1.0 (10 April 1997)",$a,0
  518.  
  519. usage.txt
  520.  dc.b    $1b,"[1;42mBootInstall V1.0"
  521.  dc.b    $1b,"[0m, Another Custom (CLI only!) Bootblock Installer !",$a
  522.  dc.b    $1b,"[3mCoded by Frédéric BASSALER.",$1b,"[0m",$a,$a
  523.  dc.b    "Usage:    BootInstall [-s] DRIVE [filename]",$a
  524.  dc.b    "Examples:",$a,$a
  525.  dc.b    " BootInstall DF1: ram:mybootblock",$a
  526.  dc.b    "  (Will install the file 'ram:mybootblock' on drive DF1:)",$a
  527.  dc.b    " BootInstall -s DF0:",$a
  528.  dc.b    "  (Will show the bootblock of the disk in DF0: - won't write anything! -)",$a,$a
  529.  dc.b    "By default, Standard OS 2.0+ bootblock is installed.",$a
  530.  dc.b    0
  531. installok.txt    dc.b    "Installation ok.",$a,0
  532. doserr.txt    dc.b    "Couldn't open dos.library!",$a,0
  533. viewbb.txt    dc.b    "ASCII dump of Bootblock...",$a,$a,0
  534. openerr.txt    dc.b    "Unable to open file!",$a,0
  535. deverr.txt    dc.b    "Unable to open disk unit number %ld!",$a,0
  536. readerr.txt    dc.b    "Read error n° %ld",$a,0
  537. writeerr.txt    dc.b    "Write error n° %ld",$a,0
  538. nodisk.txt    dc.b    "No disk in drive!",$a,0
  539. protected.txt    dc.b    "Disk is write protected!",$a,0
  540.     even
  541.  
  542. *** Start of built-in bootblock
  543. boot:
  544.     dc.b    'DOS',0
  545.     dc.l    0
  546.     dc.l    $370
  547. *** Standard OS 2.0+ bootcode (works with OS 1.3 too)
  548.     lea    expansion.name(pc),a1
  549.     moveq    #37,d0
  550.     jsr    OpenLibrary(a6)
  551.     tst.l    d0
  552.     beq.b    .err
  553.     move.l    d0,a1
  554.     bset    #6,34(a1)
  555.     jsr    CloseLibrary(a6)
  556. .err    lea    dos.name(pc),a1
  557.     jsr    FindResident(a6)
  558.     tst.l    d0
  559.     beq.b    .nodos
  560.     move.l    d0,a0
  561.     move.l    22(a0),a0
  562.     moveq    #0,d0
  563.     rts    
  564. .nodos    moveq    #-1,d0
  565.     rts
  566.  
  567. dos.name    dc.b    'dos.library',0
  568. expansion.name    dc.b    'expansion.library',0
  569.  
  570. end:
  571.